#include "xdecode_task.h"
#include "xtools.h"
#include <iostream>
#include <chrono>
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
}
using namespace std;
using namespace chrono;
void XDecodeTask::Clear() {
	pkt_list_.Clear();
	unique_lock<mutex> lock(mtx_);
	for (auto& f : this->frames_) {
		av_frame_free(&f);
	}
	frames_.clear();
	cur_pts_ = -1;
	decode_.Clear();
}
void XDecodeTask::Stop()
{
	pkt_list_.Clear();
	XThread::Stop();
	unique_lock<mutex> lck(mtx_);
	// 清理
	if (time_base_)
		delete time_base_;
	time_base_ = nullptr;
	decode_.set_c(nullptr);
	is_open_ = false;
	if (frame_)
		av_frame_free(&frame_);
	for (auto& f : this->frames_) {
		av_frame_free(&f);
	}
	frames_.clear();
}

void XDecodeTask::set_time_base(const AVRational* time_base)
{
	if (!time_base)return;
	unique_lock<mutex> lck(mtx_);
	if (time_base_)
		delete time_base_;
	time_base_ = new AVRational;
	time_base_->num = time_base->num;
	time_base_->den = time_base->den;
}

bool XDecodeTask::Open(AVCodecParameters* para) {
	decode_.set_c(nullptr);
	if (!para) {
		LOGERROR("para is null");
		return false;
	}
	unique_lock<mutex> lck(mtx_);
	is_open_ = false;
	auto c = decode_.Create(int(para->codec_id), false);
	if (!c) {
		LOGERROR("create decoder failed");
		return false;
	}
	// 复制视频参数
	avcodec_parameters_to_context(c, para);
	decode_.set_c(c);
	if (!decode_.Open()) {
		LOGERROR("XDecodeTask::Open() failed");
		return false;
	}
	LOGINFO("open decoder success");
	is_open_ = true;
	return true;
}

// 责任链处理函数
void XDecodeTask::Do(AVPacket* pkt) {
	cout << '#' << endl;
	if (!pkt || pkt->stream_index != stream_index_) // 判断是否是视频
	{
		return;
	}
	pkt_list_.Push(pkt);
	if (block_size_ <= 0)return;
	while (!is_exit_) {
		if (pkt_list_.Size() >= block_size_) {
			MSleep(1);
			continue;
		}
		break;
	}
}

AVFrame* XDecodeTask::GetFrame() {
	unique_lock<mutex> lock(mtx_);
	// 如果启动了缓存队列
	if (frame_cache_) {
		if (frames_.empty())return nullptr;
		auto f = frames_.front();
		frames_.pop_front();
		return f;
	}
	if (!need_view_ || !frame_ || !frame_->buf[0])
		return nullptr;
	auto f = av_frame_clone(frame_);
	if (!f) {
		PrintErr(AVERROR(ENOMEM));
		return nullptr;
	}
	need_view_ = false;
	return f;
}


void XDecodeTask::Main() {
	{
		unique_lock<mutex> lck(mtx_);
		if (!frame_)
			frame_ = av_frame_alloc();
	}
	while (!is_exit()) {
		if (is_pause()) {
			MSleep(1);
			continue;
		}
		// 同步
		while (!is_exit_) {
			if (syn_pts_ >= 0 && cur_pts_ > syn_pts_) {
				MSleep(1);
				continue;
			}
			break;
		}
		auto pkt = pkt_list_.Pop();
		if (!pkt) {
			this_thread::sleep_for(1ms);
			continue;
		}
		// 发送到解码线程
		bool re = decode_.Send(pkt);
		av_packet_free(&pkt);
		if (!re) {
			LOGERROR("decode.Send() failed");
			this_thread::sleep_for(1ms);
			continue;
		}
		{ // 输出
			unique_lock<mutex> lck(mtx_);
			if (decode_.Receive(frame_)) {
				cout << "@" << flush;
				need_view_ = true;
				cur_pts_ = frame_->pts;
				if (time_base_)
				{
					// 转成毫秒
					// cur_ms_ = frame_->pts * (time_base_->num * 1000) / time_base_->den;
					// 这里用av_rescale_q更保险一些
					cur_ms_ = av_rescale_q(frame_->pts, *time_base_, { 1,1000 });
					cout << "cur_ms=" << cur_ms_<<endl;
				}
			}
			if (frame_cache_) {
				auto f = av_frame_alloc();
				av_frame_ref(f, frame_);// 引用计数
				frames_.push_back(f);
			}
		}
		this_thread::sleep_for(1ms);
	}
}
